/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
/* eslint-disable @typescript-eslint/no-unused-vars */
//2.2.2.1 简单类装饰器
function logClass(constructor: Function) {
  console.log(`Class ${constructor.name} is decorated`);
}

@logClass
class MyClass {
  constructor() {}
}

//类装饰器工厂 装饰器工厂是一个返回装饰器函数的函数，可以接受参数来控制装饰器的行为。
// prefix: string 是装饰器工厂的参数，用于控制装饰器的行为。

function logClassWithParams(prefix: string) {
  return function (constructor: Function) {
    console.log(`${prefix} Class ${constructor.name} is decorated`);
  };
}

@logClassWithParams('tetst')
class MyClass2 {
  constructor(public name: string) {}
}

/**
 * 类装饰器工厂函数，用于为目标类添加 timestamp 属性
 * @param T - 泛型参数，约束传入的必须是构造函数类型
 * @param constructor - 目标类的构造函数
 * @returns 返回一个新的类，该类继承自目标类并添加了 timestamp 属性
 */
function addTimestamp<T extends { new (...args: any[]) }>(constructor: T) {
  // 返回一个新的类，继承自传入的构造函数对应的类，并添加 timestamp 属性
  return class extends constructor {
    // 添加 timestamp 属性，值为创建实例时的当前时间
    timestamp = new Date();
  };
}

/**
 * Document 类的接口定义，可用于约束 Document 类的结构
 */
interface Document {
  timestamp: Date;
}
@addTimestamp
class Document {
  constructor(public title: string) {}
}

const doc = new Document('My Document');
//const doc = new Document("My Document") as Document & { timestamp: Date };
console.log(doc.title); // My Document
console.log(doc.timestamp); // 当前日期和时间
export {};

// 4. 替换类的构造函数 可以通过返回一个新的构造函数来替换原有的构造函数，从而修改类的实例化过程。
/**
 * 类装饰器，用于替换目标类的构造函数，在实例化时添加额外的日志输出
 * @param T - 泛型参数，约束传入的必须是构造函数类型，该构造函数返回一个对象
 * @param constructor - 目标类的构造函数
 * @returns 返回一个新的类，继承自目标类并修改了构造函数
 */
function replaceConstructor<T extends { new (...args: any[]): {} }>(
  // 目标类的构造函数
  constructor: T,
) {
  // 返回一个新的类，继承自传入的构造函数对应的类
  return class extends constructor {
    /**
     * 新的构造函数，在调用父类构造函数后输出实例创建的日志
     * @param args - 传递给父类构造函数的参数
     */
    constructor(...args: any[]) {
      // 调用父类的构造函数
      super(...args);
      // 输出实例创建的日志
      console.log('Instance created');
    }
  };
}
